<template>
    <div ref="codeContainer" class="code-editor" />
</template>

<script setup>
import { toRaw, ref, reactive, toRefs, watch, onMounted, defineProps } from 'vue'
import * as monaco from 'monaco-editor';
import { useForm } from 'ant-design-vue/es/form';

const emit = defineEmits(['update:modelValue', 'change'])

const props = defineProps({
    // 编辑器的值
    modelValue: { type: [String, Object], default: '' },
    // 语言类型
    language: { type: String, default: 'javascript' },
    // 是否只读
    readOnly: { type: Boolean, default: false },
    // 值格式
    valueFormat: { type: String, default: 'json' },
    // 代码小地图
    minimap: { type: Boolean, default: false },
    // 主题
    theme: { type: String, default: 'vs' },
    // 代码折叠
    folding: { type: Boolean, default: true },
    // 显示行号
    lineNumbers: { type: Boolean, default: true },

    triggerChange: { type: Boolean, default: true }
})

const codeContainer = ref(null);
let data = reactive({
    monacoEditor: null, // 语言编辑器
})

// 监听数据的变化
watch(() => props.modelValue, (newValue, oldValue) => {
    // console.log("监听到了值变化了");
    // if (newValue == oldValue) {
    // console.log("新值和旧值相同")
    if (!data.monacoEditor?.hasTextFocus()) {
        // testWatchFunc();
        setValue(newValue);
    }
    // }
    // if (newValue != oldValue) {
    // console.log("新值和旧值不相同")
    // }
}, { deep: true })

const testWatchFunc = () => {
    // console.log("执行了testWatchFunc方法");
}

/**
 * @method
 * @desc 设置monaco编辑器的值
 * @param {String,Object} value 设置的值
 */
const setValue = (value) => {
    // console.log("执行了setValue方法")
    // toRaw(data.monacoEditor).setValue(JSON.stringify(value, null, 2));
    if (typeof value === 'string') {
        toRaw(data.monacoEditor).setValue(value);
    } else if (typeof value === 'object') {
        toRaw(data.monacoEditor).setValue(JSON.stringify(value, null, 2));
    }
}

// 页面渲染成功后
onMounted(() => {
    // 定义自定义主题
    monaco.editor.defineTheme("customTheme", {
        base: "vs",
        inherit: true,
        rules: [],
        colors: {
            "editor.foreground": "#000000",
            "editor.background": "#F5F5F5",
            "editorCursor.foreground": "#8B0000",
            "editor.lineHighlightBackground": "#E8E8E8",
            "editorLineNumber.foreground": "#000",
            "editor.selectionBackground": "#E8E8E8",
            "editor.inactiveSelectionBackground": "#CCC",
        },
    });


    data.monacoEditor = monaco.editor.create(codeContainer.value, {
        readOnly: props.readOnly,
        language: props.language,
        lineNumbers: props.lineNumbers ? "on" : "off",
        theme: props.theme,
        value: getValue(), // 初始值
        folding: props.folding, // 是否折叠
        foldingStrategy: 'indentation', // 代码可分小段折叠
        automaticLayout: true, // 自适应布局
        autoIndent: true,
        overviewRulerBorder: false, // 不要滚动条的边框
        autoClosingBrackets: true,
        scrollBeyondLastLine: true,
        tabSize: 2, // tab 缩进长度
        minimap: {
            enabled: props.minimap, // 代码小地图
        },
        wordWrap: 'off',
        wordWrapColumn: 210,
        disableLayerHinting: true, // 等宽优化
    });

    // 获取值
    function getValue() {
        if (props.valueFormat === 'json') {
            if (props.modelValue) {
                // return props.modelValue;
                return JSON.stringify(props.modelValue, null, 2)
            }
        } else {
            return props.modelValue;
        }
        // return ''
    }


    data.monacoEditor.onDidChangeModelContent(() => {
        // console.log("改变了值！！！");
        if (props.triggerChange) {
            const currenValue = toRaw(data.monacoEditor).getValue();
            // console.log("改变了编辑器的值：", currenValue)
            // console.log("编辑器的值类型：", typeof currenValue)
            if (props.valueFormat === 'json' && currenValue) {
                if (currenValue != null && currenValue != undefined && currenValue != '') {
                    emit("change", currenValue);
                }
                emit('update:modelValue', JSON.parse(currenValue))


                return
            } else {
                emit('update:modelValue', currenValue)
            }
        }

    });
})

const jsonFormate = (value) => {
    setValue();
}

defineExpose({
    setValue
})


</script>

<style lang="less" scoped>
.code-editor {
    width: 100%;
    height: 100%;

    :deep(.monaco-editor) {
        height: 100%;
    }
}
</style>